tablew.base <- function(vnames, weights, universe, dataset.name=dsn) {
  
  #    Args: vnames, name(s) of variables of tabulation as character vector;
  #          named variables must be present in workspace
  #          weights, numeric vector of weights
  #          universe, logical vector, table is made only for TRUE records
  #          dataset name
  # Result: n-dimensional array with dimnames assigned in workspace
  
  source("Rfunctions.base/getmetadata.R")

  # Get variable codes, values and dims
  dims    <- numeric(0)
  codes   <- list()
  values  <- list()
  for (i in 1:length(vnames)) {
    codes[[i]]  <- getmetadata(vnames[i])$codes
    values[[i]] <- getmetadata(vnames[i])$vshort
    dims        <- c(dims, length(codes[[i]]))
  }
  names(codes)  <- vnames
  names(values) <- vnames

  # Construct zero-initialized tabulation-as-vector
  groups <- codes[[1]]
  if (length(codes) >= 2) {
    for (i in 2:length(codes)) {
      groups <- as.vector(outer(groups, codes[[i]], FUN="paste", sep=""))    
    }
  }
  tav <- rep(0, times=length(groups))
  names(tav) <- groups
  rm(codes, groups)

  # Reduce variable and weight vectors to universe (unless all are TRUE)
  if (!all(universe)) {
    cat("tablew.base: Reducing variable and weight vectors to universe ...\n")
    weights <- weights[universe]
    for (i in 1:length(vnames)) {
      assign(vnames[i], get(vnames[i])[universe])
    }  
  }
  
  # Create compound variable for tabulation
  cat("tablew.base: Creating compound variable for tabulation ...\n")
  cvft <- get(vnames[1])
  if (length(vnames) >= 2) {
    for (i in 2:length(vnames)) {
      cvft <- paste(cvft, get(vnames[i]), sep="")
    }
  }

  # Produce and return cross-tabulation
  cat("tablew.base: Tabulating ...\n")
  tav.nz <- rowsum(weights, cvft)[, 1]
  tav[names(tav.nz)] <- tav.nz
  array(tav, dim=dims, dimnames=values)
  
}